package com.chukun.gateway.common.rule;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @author chukun
 * @version 1.0.0
 * @description 规则对象
 * @createTime 2023/11/19 20:59
 */
@Data
public class Rule implements Comparable<Rule>, Serializable {

    /**
     * 全局唯一规则ID
     */
    private String id;

    /**
     * 规则名称
     */
    private String name;

    /**
     * 规则对应的协议
     */
    private String protocol;

    /**
     * 后端服务ID
     */
    private String  serviceId;
    /**
     * 请求前缀
     */
    private String prefix;
    /**
     * 路径集合
     */
    private List<String> paths;
    /**
     * 规则排序，对应场景：一个路径对应多条规则，然后只执行一条规则的情况
     */
    private Integer order;

    /**
     * 规则优先级
     */
    private Set<FilterConfig> filterConfigs = new HashSet<>();

    /**
     * 限流规则
     */
    private Set<FlowControlConfig> flowCtlConfigs = new HashSet<>();

    /**
     * 重试配置
     */
    private RetryConfig retryConfig = new RetryConfig();

    /**
     * hystrix熔断配置
     */
    private Set<HystrixConfig> hystrixConfigs = new HashSet<>();



    public Rule(){
        super();
    }

    public Rule(String id, String name, String protocol,String serviceId, String prefix, List<String> paths, Integer order, Set<FilterConfig> filterConfigs) {
        super();
        this.id = id;
        this.name = name;
        this.protocol = protocol;
        this.serviceId = serviceId;
        this.prefix = prefix;
        this.paths = paths;
        this.order = order;
        this.filterConfigs = filterConfigs;
    }

    /**
     * 处理器配置类
     */
    @Getter
    @Setter
    public static class FilterConfig {
        /**
         * 规则配置ID
         */
        private String id;
        /**
         * 配置信息
         */
        private String config;

        public void setId(String id) {
            this.id = id;
        }

        public void setConfig(String config) {
            this.config = config;
        }

        @Override
        public boolean equals(Object o) {
            if(this == o){
                return true;
            }
            if (o == null || getClass() !=o.getClass()) {
                return  false;
            }
            FilterConfig that = (FilterConfig)o;
            return id.equals(that.id);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id);
        }
    }

    /**
     * 限流的配置规则
     */
    @Getter
    public static class FlowControlConfig {
        /**
         * 限流类型-可能是path，也可能是IP或者服务
         */
        private String type;
        /**
         * 限流对象的值
         */
        private String value;
        /**
         * 限流模式-单机还有分布式
         */
        private String model;
        /**
         * 限流规则,是一个JSON
         */
        private String config;

        public void setType(String type) {
            this.type = type;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public void setModel(String model) {
            this.model = model;
        }

        public void setConfig(String config) {
            this.config = config;
        }
    }

    /**
     * 重试配置
     */
    @Getter
    public static class RetryConfig {
        private int times;

        public void setTimes(int times) {
            this.times = times;
        }
    }

    @Data
    public static class HystrixConfig {
        private String path;
        private int timeoutInMilliseconds;
        private int threadCoreSize;
        private String  fallbackResponse;
    }

    /**
     * 向规则里面提供一些新增配置的方法
     * @param filterConfig 过滤器配置类
     * @return
     */
    public  boolean addFilterConfig(FilterConfig filterConfig){
        return filterConfigs.add(filterConfig);
    }

    /**
     * 通过指定的ID获取指定的配置信息
     * @param id 规则id
     * @return
     */
    public  FilterConfig getFilterConfig(String id){
        return filterConfigs.stream().filter(filter -> filter.getId().equalsIgnoreCase(id)).findFirst().orElse(null);
    }


    /**
     * 通过传入的FilterID判断配置信息是否存在
     * @param id 规则id
     * @return
     */
    public  boolean hasId(String id){
        return filterConfigs.stream().anyMatch(filter -> filter.getId().equalsIgnoreCase(id));
    }

    @Override
    public int compareTo(Rule o) {
        int orderCompare = Integer.compare(getOrder(),o.getOrder());
        if (orderCompare == 0){
            return  getId().compareTo(o.getId());
        }
        return orderCompare;
    }

    @Override
    public boolean equals(Object o) {
        if(this == o){
            return true;
        }
        if (o == null || getClass() !=o.getClass()) {
            return  false;
        }
        Rule that = (Rule) o;
        return id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
